/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "ui2D编辑视口.h"


C_2D编辑视口* C_2D编辑视口::g当前操作2D编辑视口 = nullptr;

static uint32	g网格线绘制属性 = 0;

static bool g移动视口 = false;

static bool on_2D编辑视口按键(C_Widget* self, const S_键盘& ks) {
	
	return false;
}

static bool on_2D编辑视口鼠标按下(C_Widget* self, const E_鼠标按钮& 按钮) {
	if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g移动视口 = true;
	}
	return false;
}

static bool on_2D编辑视口鼠标放开(C_Widget* self, const E_鼠标按钮& 按钮) {
	if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g移动视口 = false;
	}
	return false;
}

static bool on_2D编辑视口移动(C_Widget* self, const ivec4& value) {
	C_2D编辑视口* box = (C_2D编辑视口*)self;

	if (g移动视口) {
		self->m_扩展视口属性->m_中心.x += C_Widget::g_鼠标.abs.x;
		self->m_扩展视口属性->m_中心.y += C_Widget::g_鼠标.abs.y;
		self->m_绘制属性更新 = true;
	}
	

	return false;
}


static void on_2D编辑视口布局(C_Widget* self, C_Widget** w, uint32 num) {
	f_Widget_计算视口缩放保持偏移比例(self);
}

static void on_2D编辑视口绘制(C_Widget* self, S_2D画布* 画布) {
	C_2D编辑视口* box = (C_2D编辑视口*)self;

	box->m_背景绘制.m_属性 = f_vg_gen属性(画布);
	g网格线绘制属性 = f_vg_gen属性(画布);


	S_凸边图元 图元 = {};
	图元.属性 = f_vg_get属性指针(画布, box->m_背景绘制.m_属性);
	box->m_背景绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色填充);

	图元 = {};
	图元.属性 = f_vg_get属性指针(画布, box->m_背景绘制.m_属性);
	box->m_背景线绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色描边);

	
	box->m_刻度线绘制.f_Draw网格(画布, g网格线绘制属性);


	图元 = {};
	图元.属性 = f_vg_get属性指针(画布, g网格线绘制属性);
	box->m_基线绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色描边);



	box->m_坐标绘制.f_Draw(画布, g网格线绘制属性, false);


	box->m_是否未绘制 = false;
}

static void on_2D编辑视口变换修改(C_Widget* self) {
	C_2D编辑视口* box = (C_2D编辑视口*)self;


	S_2D顶点属性 属性 = { {1,1}, {0,0}, 1, 3 };
	//属性.m_偏移 = {0, self->m_扩展视口属性->m_中心.y};
	//属性.m_间隔 = uint32(box->m_Size.x)<<16 | uint32(box->m_Size.y);
	f_vg_set属性(self->m_画布, box->m_背景绘制.m_属性, 属性);

	属性 = { {1,1}, {0,0}, 1, 3 };
	属性.m_比例 = self->m_扩展视口属性->m_比例;
	属性.m_偏移 = self->m_扩展视口属性->m_中心;
	//属性.m_渐变数量 = box->m_GPU内存分配维度大小.x;
	属性.m_间隔 = 3;
	f_vg_set属性(self->m_画布, g网格线绘制属性, 属性);


	box->m_背景绘制.f_alloc(1);
	mat3X2 mat;
	mat.row0 = {};
	mat.row1 = self->m_Size;
	mat.row2 = {};
	box->m_背景绘制.f_set单色填充(0, mat, S_UI主题::uic_页面焦点标签, S_Widget预设图元::m_矩形);

	box->m_基线绘制.f_alloc(2);
	vec2 point[4] = { { -100,0 }, { self->m_Size.x / 属性.m_比例.x, 0 }, { 0,-100 }, { 0,100 } };
	uint32 添加线后顶点偏移 = box->m_基线绘制.f_fill顶点(point, 4);

	mat = { {}, {1,1}, {1,0} };
	S_LineProp 线属性 = {0, f_PackData4X8({ 200,50,50,255 }), f_PackData4X8({ 200,50,50,255 }) };
	box->m_基线绘制.f_set单色线(0, mat, 线属性, { 添加线后顶点偏移, 添加线后顶点偏移+2 }, 2);

	线属性 = { 0, f_PackData4X8({ 50,200,50,255 }), f_PackData4X8({ 50,200,50,255 }) };
	box->m_基线绘制.f_set单色线(1, mat, 线属性, { 添加线后顶点偏移 + 2, 添加线后顶点偏移+4 }, 2);

	//box->m_基线绘制.f_set顶点(0, { 0,0 }, { 200,50,50,255 });
	//box->m_基线绘制.f_set顶点(1, { 100,0 }, { 200,50,50,255 });
	//box->m_基线绘制.f_set顶点(2, { 0,0 }, { 50,200,50,255 });
	//box->m_基线绘制.f_set顶点(3, { 0,100 }, { 50,200,50,255});

	vec2 帧绘制间隔宽度 = self->m_Size;
	vec2 刻度线步进宽度 = f_时间工作区_计算尺线绘制间隔(帧绘制间隔宽度);
	box->m_刻度线绘制.f_alloc(1);
	mat.row0 = {};
	mat.row1 = self->m_Size;
	mat.row2 = 刻度线步进宽度 * 2;
	box->m_刻度线绘制.f_set(2048, mat, S_主题颜色::uic_时间网格线);
	

	box->f_数据绘制();
}



C_2D编辑视口::C_2D编辑视口(S_UI创建环境& ctx) : C_Widget(&ctx) {
	mf_布局Fun = on_2D编辑视口布局;
	mf_DrawFun = on_2D编辑视口绘制;
	mf_变换修改 = on_2D编辑视口变换修改;
	mf_鼠标移动 = on_2D编辑视口移动;

	mf_鼠标按键按下 = on_2D编辑视口鼠标按下;
	mf_鼠标按键放开 = on_2D编辑视口鼠标放开;

	m_是否未绘制 = true;
	g当前操作2D编辑视口 = this;

	
}

C_2D编辑视口::~C_2D编辑视口() {
	C_Widget::~C_Widget();
}

void C_2D编辑视口::f_数据绘制() {
	for (auto& node : m_节点) {
		//node->f_getStr(m_绘制文本);
	}
	if(m_是否未绘制) return;

	std::vector<vec2> 顶点坐标;
	std::vector<uint32> 顶点索引;

	m_物体.clear();
	for (auto& ob : S_节点数据::g_选中激活物体) {
		switch (ob->m_Type) {
		case E_物体类型::t_网格: 
		case E_物体类型::t_多边形: {
			m_物体.insert(ob);
			break;
		}
		}
		std::cout<<"ob " << ob->m_Type << std::endl;
	}

	for (auto& ob : m_物体) {
		if(!ob->m_UserData) continue;

		auto* 物体扩展属性 = f_OE_取可编辑物体属性(ob);

		uint32 面数量 = ((S_多边形*)ob->m_UserData)->m_面.size();
		auto* faces = ((S_多边形*)ob->m_UserData)->m_面.data();

		auto* uv索引 = ((S_多边形*)ob->m_UserData)->m_UV索引.data();
		//auto* uv坐标 = ((S_多边形*)ob->m_UserData)->m_UV.data();
		

		uint32 UV通道显示开关 = 1;
		if (物体扩展属性) {
			UV通道显示开关 = f_prop_UI32(物体扩展属性->m_当前激活UV层);
		}
		

		for (uint32 i = 0; i < 面数量; ++i) {
			auto* uvIndex = faces[i]->uvLoopIndex.data();
			uint32 layerNum = faces[i]->uvLoopIndex.size();
			
			for (uint32 u = 0; u<layerNum; ++u) {
				if (UV通道显示开关 & 1 << u) {
					auto uvLoop = uvIndex[u];
					uint32 loopNum = uvLoop.y;
					for (uint32 j = 0; j < loopNum; ++j) {
						顶点索引.push_back(uv索引[uvLoop.x + j]);
					}
					顶点索引.push_back(uv索引[uvLoop.x]);
					顶点索引.push_back(0xffffffff);
				}
			}
		}

		顶点坐标 = ((S_多边形*)ob->m_UserData)->m_UV;
	}

	if(顶点索引.size()) 顶点索引.pop_back();

	mat3X2 mat;
	mat.row0 = {};
	mat.row1 = m_Size;
	mat.row2 = {};
	m_坐标绘制.f_fill(mat, 顶点坐标, 顶点索引);
}

C_Widget* f_工作区页面_创建2D视口(S_UI创建环境& ctx) {
	C_2D编辑视口* ui2D编辑视口 = new C_2D编辑视口(ctx);

	f_widget_开启视口属性(ui2D编辑视口);
	ui2D编辑视口->m_扩展视口属性->m_大小 = { 2048, 2048 };
	ui2D编辑视口->m_属性栏 = f_创建属性边栏(ctx);

	auto* 滚动窗口 = f_ui_创建滚动框(ctx, true, true, ui2D编辑视口);
	滚动窗口->mf_鼠标滚轮 = nullptr;

	C_2D编辑视口::g当前操作2D编辑视口 = ui2D编辑视口;



	S_鼠标键位映射* 鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_缩放页面视口;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_滚轮;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->发生组件 = ui2D编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);


	return 滚动窗口;
}
